package helper.com.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;


/**
 * <p>
 *     controller日志切面,记录每个请求的执行时间
 * </p>
 * @author 大忽悠
 * @create 2022/5/1 20:37
 */
@Aspect
@Component
@Slf4j
public class ControllerLogAop {
    /**
     * 慢查询时间分割线
     */
    private static final long SLOW_QUERY_TIME=1000L;

    @Pointcut("execution(* helper.com.controller.*.*(..))")
    public void point(){}

    @Around("point()")
    public Object calculateMethodTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long end = System.currentTimeMillis();
        logIfOverTheSlowTime(joinPoint, start, end);
        return proceed;
    }

    /**
     * 对超过慢响应时间的请求进行日志记录
     */
    private void logIfOverTheSlowTime(ProceedingJoinPoint joinPoint, long start, long end) {
        long count= end - start;
        if(count>SLOW_QUERY_TIME){
            Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
            StringBuilder logInfo=new StringBuilder();
            logInfo.append("请求的资源路径为: ");
            logRequestUrl(method, logInfo);
            logInfo.append(" ,请求耗时为: "+count);
            logInfo.append(" ,请求的发生时间为: "+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒")));
            //记录到日志中去
            log.warn(logInfo.toString());
        }
    }

    private void logRequestUrl(Method method, StringBuilder logInfo) {
        String[] value=null;
        if(method.isAnnotationPresent(GetMapping.class)){
            value = method.getAnnotation(GetMapping.class).value();
        }else if(method.isAnnotationPresent(PostMapping.class)){
            value = method.getAnnotation(PostMapping.class).value();
        }else if(method.isAnnotationPresent(DeleteMapping.class)){
            value = method.getAnnotation(DeleteMapping.class).value();
        }else if(method.isAnnotationPresent(PutMapping.class)){
            value = method.getAnnotation(PutMapping.class).value();
        }else if(method.isAnnotationPresent(RequestMapping.class)){
            value = method.getAnnotation(RequestMapping.class).value();
        }
        logInfo.append((value==null||value.length==0)?"":value[0]);
    }
}
